﻿#ifndef __AF_TABLE_H__
#define __AF_TABLE_H__

namespace AF
{
	//template<class T> class Struct -* _INTERFACE ForEach
		template<class T> class Table;
}
#define AF_CTable			AF::Table

#include "AF_Struct.h"
#include "AF_Array.h"

namespace AF
{
	/// 表结构模板类
	template<class T>
	class Table : public Struct<T>
	{
	private:
		struct Node
		{
			_STRING		strKey;
			T		tType;
		};

	public:
		Table();
		virtual ~Table();

		/// 添加表项
		bool			Put(const _STRING strKey, const T& tNode);
		/// 移除表项
		bool			Remove(const _STRING strKey);
		/// 清除全部表项
		bool			Clean(T* ptReturn = NULL);
		/// 销毁全部表项
		bool			Destroy(T* ptReturn = NULL);

		/// 获得指定Key值的内容
		T&			Get(const _STRING strKey);

		void*			Foreach(bool bFirst);
		UINT			GetCount();

		void			SetGrow(UINT nNum);		// 设置每次增加数
		bool			FreeExtra();			// 释放大于当前上界的未使用的内存

		int			Find(const _STRING strKey);

	private:
		T			m_tNull;
		Array<Node*>		m_aryNodes;
		UINT			m_nCurID;
	};
//****


//**** 实现部分
	template<class T>
	Table<T>::Table() :
		m_nCurID(0)
	{
		_MEMSET(&m_tNull, 0, sizeof(T));
	}

	template<class T>
	Table<T>::~Table()
	{
		Destroy();
	}

	template<class T>
	bool Table<T>::Put(const _STRING strKey, const T& tNode)
	{
		if(Find(strKey) >= 0)
			return false;

		Node* pNode = AF_NEW(Node);
		pNode->strKey = strKey;
		_MEMCPY(&pNode->tType, &tNode, sizeof(T));
		return m_aryNodes.Add(pNode);
	}

	template<class T>
	bool Table<T>::Remove(const _STRING strKey)
	{
		int nID = Find(strKey);
		if(nID < 0)
			return false;

		Node* pNode = m_aryNodes.GetAt(nID);
		m_aryNodes.Remove(nID);
		AF_DELETE(pNode);
		return true;
	}

	template<class T>
	bool Table<T>::Clean(T* ptReturn)
	{
		int _nCount = m_aryNodes.GetCount();
		Node** _ppNode = AF_NEW_ARY(Node*, _nCount);
		m_aryNodes.Clean(_ppNode);

		Node* pNode = NULL;
		for(int i = 0; i < _nCount; i++)
		{
			pNode = _ppNode[i];

			if(ptReturn != NULL)
				// catch
				_MEMCPY(&ptReturn[i], &(pNode->tType), sizeof(T));

			AF_DELETE(pNode);
		}
		AF_DELETE_ARY(_ppNode);

		return true;
	}

	template<class T>
	bool Table<T>::Destroy(T* ptReturn)
	{
		int nCount = m_aryNodes.GetCount();
		if(nCount <= 0)
			return true;

		Node** ppNode = AF_NEW_ARY(Node*, nCount);
		m_aryNodes.Destroy(ppNode);

		Node* pNode = NULL;
		for(int i = 0; i < nCount; i++)
		{
			pNode = ppNode[i];

			if(ptReturn != NULL)
				// catch
				_MEMCPY(&ptReturn[i], &(pNode->tType), sizeof(T));

			AF_DELETE(pNode);
		}
		AF_DELETE_ARY(ppNode);

		return true;
	}


	template<class T>
	T& Table<T>::Get(const _STRING strKey)
	{
		int nID = Find(strKey);
		if(nID < 0)
			return m_tNull;

		Node* _pNode = m_aryNodes.GetAt(nID);
		return _pNode->tType;
	}

	template<class T>
	void* Table<T>::Foreach(bool isFirst)
	{
		if(isFirst)
			m_nCurID = 0;

		if(m_nCurID >= m_aryNodes.GetCount())
			return NULL;

		Node* _pNode = m_aryNodes.GetAt(m_nCurID++);
		return &_pNode->tType;
	}

	template<class T>
	UINT Table<T>::GetCount()
	{
		return m_aryNodes.GetCount();
	}

	template<class T>
	void Table<T>::SetGrow(UINT nNum)
	{
		m_aryNodes.SetGrow(nNum);
	}

	template<class T>
	bool Table<T>::FreeExtra()
	{
		m_aryNodes.FreeExtra();
	}

	template<class T>
	int Table<T>::Find(const _STRING strKey)
	{
		int _nID = -1;
		for(UINT _i = 0 ; _i < m_aryNodes.GetCount(); _i++)
		{
			Node* pNode = m_aryNodes.GetAt(_i);
			if(pNode->strKey == strKey)
			{
				_nID = _i;
				break;
			}
		}
		return _nID;
	}
}

#endif